﻿//++
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Module Name:
//
//  OperationalLogsTest.cs
//    
// Abstract:
//
//  Unit tests for the OperationalLogs class.
//  
//--

using System;
using System.Collections.Generic;
using System.Diagnostics;

using Microsoft.OfficeCommunicationsServer.Applications.Common;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.EnhancedReminders.Common.UnitTests
{
    /// <summary>
    /// Summary description for OperationalLogsTests
    /// </summary>
    [TestClass]
    public class OperationalLogsTest
    {
        private const string _source = "Enhanced Reminders Common Unit Tests";
        private const string _logName = "ERTstLog";

        /// <summary>
        /// Tests all the static log methods.
        /// </summary>
        [TestMethod]
        public void TestAllMethods()
        {
            if (!EventLog.SourceExists(_source))
            {
                // Create the event log to be used by these tests
                EventLog.CreateEventSource(_source, _logName);
            }

            // Need to wait for the source to be registered
            for (int i = 0; i < 20 && !EventLog.SourceExists(_source); i++)
            {
                System.Threading.Thread.Sleep(1000);
            }

            Assert.IsTrue(EventLog.SourceExists(_source), "EventLog.SourceExists(_source)");

            // Open the event log and make sure it is empty
            EventLog eventLog = new EventLog(_logName);
            eventLog.Source = _source;
            eventLog.Clear();

            List<long> expectedEventId = new List<long>();
            List<EventLogEntryType> expectedEventType = new List<EventLogEntryType>();

            // Initialize the logger
            Logger.Initialize(_source, TraceLogLevel.None, false);

            OperationalLogs.LogMessageQueueError("queueName", new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x01);

            OperationalLogs.LogMessageQueueFatalError("queueName", new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x02);

            OperationalLogs.LogFindingCasError("user");
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x03);

            OperationalLogs.LogMailboxAccessError("user", new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x04);

            OperationalLogs.LogMailboxItemAccessError("user", new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x05);

            OperationalLogs.LogMissingSettingError("settingName");
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x06);

            OperationalLogs.LogInvalidSettingError("settingName");
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x07);

            OperationalLogs.LogNoUsersWarning();
            expectedEventType.Add(EventLogEntryType.Warning);
            expectedEventId.Add(0x08);

            OperationalLogs.LogNoUsersError();
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x09);

            OperationalLogs.LogServiceStartingInformation();
            expectedEventType.Add(EventLogEntryType.Information);
            expectedEventId.Add(0x0A);

            OperationalLogs.LogServiceStartedInformation();
            expectedEventType.Add(EventLogEntryType.Information);
            expectedEventId.Add(0x0B);

            OperationalLogs.LogServiceStoppingInformation();
            expectedEventType.Add(EventLogEntryType.Information);
            expectedEventId.Add(0x0C);

            OperationalLogs.LogServiceStoppedInformation();
            expectedEventType.Add(EventLogEntryType.Information);
            expectedEventId.Add(0x0D);

            OperationalLogs.LogServiceShutdownTimeoutWarning(0);
            expectedEventType.Add(EventLogEntryType.Warning);
            expectedEventId.Add(0x0E);

            OperationalLogs.LogServiceStartError(new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x0F);

            OperationalLogs.LogScratchDirectoryCreateError("scratcheDirectoryPath", new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x10);

            OperationalLogs.LogScratchDirectoryCleanupWarning("scratcheDirectoryPath", new Exception());
            expectedEventType.Add(EventLogEntryType.Warning);
            expectedEventId.Add(0x11);

            OperationalLogs.LogNoSipAddressError("user");
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x12);

            OperationalLogs.LogVoiceNotificationError("user", new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x13);

            OperationalLogs.LogSmsNotificationError("user", new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x14);

            OperationalLogs.LogInstantMessageNotificationError("user", new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x15);

            OperationalLogs.LogNotificationDeliveryError("reason", "queueName");
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x16);

            OperationalLogs.LogSipUnreachableError("address", new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x17);

            OperationalLogs.LogSipRegistrationError("address", new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x18);

            OperationalLogs.LogScratchDirectoryWriteError("scratcheDirectoryPath", new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x19);
            
            OperationalLogs.LogScratchDirectoryDeleteWarning("scratcheDirectoryPath", new Exception());
            expectedEventType.Add(EventLogEntryType.Warning);
            expectedEventId.Add(0x1A);

            OperationalLogs.LogActiveDirectorySearchError("activeDirectoryRoot", new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x1B);

            OperationalLogs.LogOcsConnectionWarning();
            expectedEventType.Add(EventLogEntryType.Warning);
            expectedEventId.Add(0x1C);

            OperationalLogs.LogReconnectedToOcs();
            expectedEventType.Add(EventLogEntryType.Information);
            expectedEventId.Add(0x1D);

            OperationalLogs.LogWindowsMediaEncoderNotFoundError(new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x1E);

            OperationalLogs.LogWindowsMediaEncoderFailedError(new Exception());
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x1F);

            OperationalLogs.LogNoNotificationsError("notificationSettingName");
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x20);

            OperationalLogs.LogConnectionEstablishedInformation();
            expectedEventType.Add(EventLogEntryType.Information);
            expectedEventId.Add(0x21);

            OperationalLogs.LogCertificateNotFoundError();
            expectedEventType.Add(EventLogEntryType.Error);
            expectedEventId.Add(0x22);

            // Close logging
            Logger.Close();

            // Verify that all the OperationalLogs methods are include above
            Type t = typeof(OperationalLogs);
            int expectedNumberEntries = t.GetMethods().Length - 4;
            Assert.AreEqual<int>(expectedNumberEntries, eventLog.Entries.Count, "Unexpected number of log entries");

            // Check each event log entry matches expectations
            for (int i = 0; i < eventLog.Entries.Count; i++)
            {
                Assert.AreEqual<long>(expectedEventId[i], eventLog.Entries[i].InstanceId, "Unexpected event ID");
                Assert.AreEqual<EventLogEntryType>(expectedEventType[i], eventLog.Entries[i].EntryType, "Unexpected log entry type");

                // Check there are no duplicate event IDs
                for (int j = i + 1; j < eventLog.Entries.Count; j++)
                {
                    Assert.AreNotEqual<long>(eventLog.Entries[i].InstanceId, eventLog.Entries[j].InstanceId, "Duplicate event ID");
                }
            }

            // Clear the event log
            EventLog.DeleteEventSource(_source);
            EventLog.Delete(_logName);
        }
    }
}
